﻿using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.IO;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Timers;
using Timer = System.Timers.Timer;

namespace RSModels
{
    public class DataMonitor : INotifyPropertyChanged
    {
        public DataMonitor()
        {
            RefreshTimer.Elapsed += RefreshTimer_Elapsed;
        }

        public event PropertyChangedEventHandler PropertyChanged;

        private async void RefreshTimer_Elapsed(object sender, ElapsedEventArgs e)
        {
            if (!IsGettingData)
            {
                try
                {
                    IsGettingData = true;
                    ValueString = await GetDataAsync();
                    if (IsRunning)
                    {
                        if (UseWarning && Convert.ToDouble(WarningValue) <= double.Parse(ValueString))
                        {
                            C1 = W1;
                            C2 = W2;
                            C3 = BR;
                            RefreshTime = DateTime.Now.ToString();
                        }
                        else
                        {
                            if (UseWarning)
                            {
                                C1 = U1;
                                C2 = U2;
                                C3 = BR;
                            }
                            else
                            {
                                C1 = N1;
                                C2 = N2;
                            }
                        }
                    }
                }
                catch (Exception ex)
                {
                    ErrorTip = ex.Message;
                }
                finally
                {
                    IsGettingData = false;
                }
            }
        }

        private string title;
        public string Title
        {
            get { return title; }
            set { title = value; PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(Title))); }
        }

        private string details;
        public string Details
        {
            get { return details; }
            set { details = value; PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(Details))); }
        }

        private string valueString = "--";
        public string ValueString
        {
            get { return valueString; }
            set { valueString = value; PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(ValueString))); }
        }

        private string refreshTime;
        public string RefreshTime
        {
            get { return refreshTime; }
            set { refreshTime = value; PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(RefreshTime))); }
        }

        private string dataPath;
        public string DataPath
        {
            get { return dataPath; }
            set { dataPath = value; PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(DataPath))); }
        }

        private string jsonText;
        public string JsonText
        {
            get { return jsonText; }
            set { jsonText = value; PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(JsonText))); }
        }

        private string httpAddress;
        public string HttpAddress
        {
            get { return httpAddress; }
            set { httpAddress = value; PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(HttpAddress))); }
        }

        private string requestMethod;
        public string RequestMethod
        {
            get { return requestMethod; }
            set { requestMethod = value; PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(RequestMethod))); }
        }

        private string errorTip;
        public string ErrorTip
        {
            get => errorTip;
            set { errorTip = value; PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(ErrorTip))); }
        }

        private string c1 = D1;
        public string C1
        {
            get { return c1; }
            set { c1 = value; PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(C1))); }
        }

        private string c2 = D2;
        public string C2
        {
            get { return c2; }
            set { c2 = value; PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(C2))); }
        }

        private string c3 = BW;
        public string C3
        {
            get { return c3; }
            set { c3 = value; PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(C3))); }
        }

        public static string W1 { get; } = "#FE8A2D";
        public static string W2 { get; } = "#FEB542";

        public static string U1 { get; } = "#3BCBCD";
        public static string U2 { get; } = "#43E9BB";

        public static string N1 { get; } = "#47A4F8";
        public static string N2 { get; } = "#40D5FF";

        public static string D1 { get; } = "#cccccc";
        public static string D2 { get; } = "#f4f4f4";

        public static string BR { get; } = "#ff3c3c";
        public static string BW { get; } = "#dddddd";

        public delegate string GetValueStringMethod(object value);

        public GetValueStringMethod GetValueString { get; set; } = (object value) => { return value.ToString(); };

        public object WarningValue { get; set; }

        public double RefreshInterval
        {
            get => RefreshTimer.Interval;
            set => RefreshTimer.Interval = value;
        }

        private Timer RefreshTimer { get; } = new Timer(500) { AutoReset = true };

        private bool IsGettingData { get; set; }

        public bool UseWarning { get; set; }

        public bool IsRunning { get; private set; }

        public void Start()
        {
            IsRunning = true;
            RefreshTimer.Start();
            if (UseWarning)
            {
                C1 = U1;
                C2 = U2;
            }
            else
            {
                C1 = N1;
                C2 = N2;
            }
        }

        public void Stop()
        {
            RefreshTimer.Stop();
            IsRunning = false;
            C1 = D1;
            C2 = D2;
            ValueString = "--";
        }

        private Task<string> GetDataAsync()
        {
            var result = new TaskCompletionSource<string>();
            new Thread(() =>
            {
                try
                {
                    HttpWebRequest httpWebRequest = (HttpWebRequest)WebRequest.Create(HttpAddress);
                    httpWebRequest.Method = "GET";
                    HttpWebResponse httpWebResponse = (HttpWebResponse)httpWebRequest.GetResponse();
                    StreamReader streamReader = new StreamReader(httpWebResponse.GetResponseStream(), Encoding.UTF8);
                    JsonText = streamReader.ReadToEnd();
                    streamReader.Close();
                    httpWebResponse.Close();
                    JObject o = JObject.Parse(JsonText);
                    result.SetResult((string)o.SelectToken(DataPath));
                }
                catch
                {
                    result.SetResult("--");
                }
            })
            { IsBackground = true }.Start();
            return result.Task;
        }

    }
}
